package com.lyfei.yd.logic;

import com.lyfei.yd.common.exception.CustomException;
import com.lyfei.yd.domain.bo.SkuOrderBo;
import com.lyfei.yd.domain.dto.OrderDto;
import com.lyfei.yd.domain.dto.SkuInfoDto;
import com.lyfei.yd.domain.entity.OrderSku;
import com.lyfei.yd.domain.entity.Sku;
import lombok.Getter;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;


public class OrderChecker {

    private OrderDto orderDto;
    private List<Sku> serverSkuList;
    private Integer maxSkuLimit;

    @Getter
    private List<OrderSku> orderSkuList = new ArrayList<>();

    public OrderChecker(OrderDto orderDto, List<Sku> serverSkuList, Integer maxSkuLimit) {
        this.orderDto = orderDto;
        this.serverSkuList = serverSkuList;
        this.maxSkuLimit = maxSkuLimit;
    }

    public String getLeaderImg() {
        return this.serverSkuList.get(0).getImg();
    }

    public String getLeaderTitle() {
        return this.serverSkuList.get(0).getTitle();
    }

    public Integer getTotalCount() {
        return this.orderDto.getSkuInfoList()
                .stream()
                .map(SkuInfoDto::getCount)
                .reduce(Integer::sum)
                .orElse(0);
    }


    public void isOK() {
        BigDecimal serverTotalPrice = new BigDecimal("0");
        List<SkuOrderBo> skuOrderBOList = new ArrayList<>();

        this.skuNotOnSale(orderDto.getSkuInfoList().size(), this.serverSkuList.size());

        for (int i = 0; i < this.serverSkuList.size(); i++) {
            Sku sku = this.serverSkuList.get(i);
            SkuInfoDto skuInfoDTO = this.orderDto.getSkuInfoList().get(i);
            this.containsSoldOutSku(sku);
            this.beyondSkuStock(sku, skuInfoDTO);
            this.beyondMaxSkuLimit(skuInfoDTO);

            serverTotalPrice = serverTotalPrice.add(this.calculateSkuOrderPrice(sku, skuInfoDTO));
            skuOrderBOList.add(new SkuOrderBo(sku, skuInfoDTO));
            this.orderSkuList.add(new OrderSku(sku, skuInfoDTO));
        }

        this.totalPriceIsOk(orderDto.getTotalPrice(), serverTotalPrice);

        if (orderDto.getFinalTotalPrice()
                .compareTo(serverTotalPrice) != 0) {
            throw new CustomException("订单金额与实际金额不匹配,可能某些商品价格有浮动");
        }
    }


    private void totalPriceIsOk(BigDecimal orderTotalPrice, BigDecimal serverTotalPrice) {
        if (orderTotalPrice.compareTo(serverTotalPrice) != 0) {
            throw new CustomException("订单金额与实际金额不匹配,可能某些商品价格有浮动");
        }
    }


    private BigDecimal calculateSkuOrderPrice(Sku sku, SkuInfoDto skuInfoDTO) {
        if (skuInfoDTO.getCount() <= 0) {
            throw new CustomException("商品数量不能小于等于0");
        }
        return sku.getPrice().multiply(new BigDecimal(skuInfoDTO.getCount()));
    }

    private void skuNotOnSale(int count1, int count2) {
        if (count1 != count2) {
            throw new CustomException("订单中有已下架商品");
        }
    }

    private void containsSoldOutSku(Sku sku) {
        if (sku.getStock() == 0) {
            throw new CustomException("订单中有商品已售罄");
        }
    }

    private void beyondSkuStock(Sku sku, SkuInfoDto skuInfoDTO) {
        if (sku.getStock() < skuInfoDTO.getCount()) {
            throw new CustomException("订单中有商品库存不足");
        }
    }

    private void beyondMaxSkuLimit(SkuInfoDto skuInfoDTO) {
        if (skuInfoDTO.getCount() > this.maxSkuLimit) {
            throw new CustomException("商品数量不能超过" + this.maxSkuLimit + "件");
        }
    }

}
